﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Runtime.InteropServices;

using OpenTK.Graphics.OpenGL;
using OpenTK;

using Core.Objects;
using Core.Helpers;


namespace Core.Graphics
{
    public class GraphEngine
    {
        [DllImport("glut32.dll")]
        public static extern void glutWireSphere(double radius, int slices, int stacks);

        public Engine Engine { get; set; }
        Vector3 up = new Vector3(0, 1, 0);
        public GraphEngine(Action renderAction)
        {
            Render = renderAction;
        }
        public HeightMap Map { get; set; }
        public Action Render { get; set; }
        public AbstractVehicle Vehicle
        {
            get
            {
                return Engine.Vehicle;
            }
        }


        internal void Draw()
        {
            if (Render != null && Vehicle != null)
            {
                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

                GL.Translate(-Vehicle.X, -Vehicle.Y, -Vehicle.Z);
                GL.Rotate(Vehicle.AngleHorizontalRad, 0, 1, 0);
                float[] pos = Vehicle.Position;
                float[] targ = Vehicle.Target;
                var lookMatrix = Matrix4.LookAt(pos[0], pos[1], pos[2], targ[0], targ[1], targ[2], 0, 1, 0);//up[0..2]
                GL.LoadMatrix(ref lookMatrix);

                //height map

                GL.Begin(PrimitiveType.Lines);
                GL.Color3(Color.Green);
                for (int i = 0; i < Constants.MAP_SIZE - 1; i++)
                {
                    for (int j = 0; j < Constants.MAP_SIZE - 1; j++)
                    {
                        GL.Vertex3(i * Constants.CELL_SIZE, Map[i, j], j * Constants.CELL_SIZE);
                        GL.Vertex3((i + 1) * Constants.CELL_SIZE, Map[i + 1, j], j * Constants.CELL_SIZE);

                        GL.Vertex3(i * Constants.CELL_SIZE, Map[i, j], j * Constants.CELL_SIZE);
                        GL.Vertex3(i * Constants.CELL_SIZE, Map[i, j + 1], (j + 1) * Constants.CELL_SIZE);
                    }
                }

                GL.End();

                DrawCross(0.01, 5, 5);

                GL.Rotate(-Vehicle.AngleHorizontalRad, 0, 1, 0);
                GL.Translate(Vehicle.X, Vehicle.Y, Vehicle.Z);
                //GL.LoadIdentity();

                GL.Flush();
                Render();
            }
        }

        private void DrawCross(double rad, int slices, int stacks)
        {
            GL.Color3(Color.Red);
            GL.Begin(PrimitiveType.Polygon);
            GL.Vertex3(Vehicle.EyeX - 0.1, Vehicle.EyeY - 0.1, Vehicle.EyeZ);

            GL.Vertex3(Vehicle.EyeX - 0.1, Vehicle.EyeY + 0.1, Vehicle.EyeZ);
            GL.Vertex3(Vehicle.EyeX + 0.1, Vehicle.EyeY + 0.1, Vehicle.EyeZ);
            GL.Vertex3(Vehicle.EyeX + 0.1, Vehicle.EyeY - 0.1, Vehicle.EyeZ);
            GL.End();

            GL.Begin(PrimitiveType.Polygon);
            GL.Vertex3(Vehicle.EyeX, Vehicle.EyeY - 0.1, Vehicle.EyeZ - 0.1);

            GL.Vertex3(Vehicle.EyeX, Vehicle.EyeY + 0.1, Vehicle.EyeZ - 0.1);
            GL.Vertex3(Vehicle.EyeX, Vehicle.EyeY + 0.1, Vehicle.EyeZ + 0.1);
            GL.Vertex3(Vehicle.EyeX, Vehicle.EyeY - 0.1, Vehicle.EyeZ + 0.1);
            GL.End();

            //glutWireSphere(rad, slices, stacks);
        }

        public void InitGraphics(int width, int height)
        {
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            float aspect = (float)width / (float)height;
            var projMatr = Matrix4.CreatePerspectiveFieldOfView(0.5f, aspect, 0.1f, 500f);
            GL.LoadMatrix(ref projMatr);
            GL.Viewport(0, 0, width, height);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
        }
    }
}
